

#include "types.h"
#include "user.h"

#define PG_SIZE 4096

void stop_for_ctrl_p()
{
  char* b[20];
  printf(1,"Press ctrl p to view statistics\nPress enter to continue\n");
  read(1,b,1);
}

char *alocatePage()
{
  char *res = sbrk(PG_SIZE);
  printf(1,"Added Page to Process %d\n",getpid());
  return res;
}
void freePages(int num,char *pages[])
{
  int i;
  for(i=0;i<num;i++)
    free(pages[i]);

}
void allocate_namber_of_pages(int num,char *pages[])
{
  int i;
  for(i=0; i<num; i++) {
    pages[i] = alocatePage();
    memset((void *)pages[i],0,PG_SIZE);
  }
}

void nfu_vs_fifo_test()
{
  char *pages[15];
  allocate_namber_of_pages(15,pages);
  int i;
  for(i=0; i<30; i++) {
    pages[0][10] = 'a';
    printf(1, "write <a> to page 0.\n");
  }
}


void forktest()
{
  printf(1,"Testing Fork...\n");
  int pageNum=5;
  char *pages[pageNum];
  stop_for_ctrl_p();
  allocate_namber_of_pages(pageNum,pages);
  printf(1,"if there is file on disk fork will take time\n");
  int pid = fork();
  printf(1,"fork complete\n");
  if(pid>0)
    {
      wait();
      printf(1,"in father\n");
      stop_for_ctrl_p();
      if(pages[0][100]=='a')
	printf(1,"fork test failed: child and father hold the same memory space for pages\n");
      freePages(pageNum,pages);
    }
  else if(pid==0)
    {
      printf(1,"in child\n");
      stop_for_ctrl_p();
      pages[0][100] = 'a';
      //freePages(pageNum,pages);
      exit();
    }
 
  printf(1,"finished foking and released pages.\nwe should leave with the same amount of pages as we started with\n");
  stop_for_ctrl_p();
}

void multiplefork()
{
  int pageNum=5;
  printf(1,"Testing multiple Fork...\n");
  char *pages[pageNum];
  stop_for_ctrl_p();
  allocate_namber_of_pages(pageNum,pages);
  int pid1=fork();
  if(pid1>0)
    {
      wait();
      int pid2=fork();
      if(pid2>0)
	{
	  wait();
	  printf(1,"in procces %d\n",getpid());
	  stop_for_ctrl_p();
	}
      else if(pid2==0)
	{
	  printf(1,"in procces %d\n",getpid());
	  stop_for_ctrl_p();
	}
    }
  else if(pid1==0)
    {
      int pid2=fork();
      if(pid2>0)
	{
	  wait();
	  printf(1,"in procces %d\n",getpid());
	  stop_for_ctrl_p();
	}
      else if(pid2==0)
	{
	  printf(1,"in procces %d\n",getpid());
	  stop_for_ctrl_p();
	}
    }
  freePages(pageNum,pages);  
}

void readtest()
{
  int pageNum=20;
  printf(1,"Testing reading from file and getting different amount of trap fault on each algorithm...\n");
  stop_for_ctrl_p();
  char *pages[pageNum];
  allocate_namber_of_pages(pageNum,pages);

  printf(1,"we should have 9 pages in the file and 15 on memory\nnow lets write 30 times to the 10th page so that in fifo he will be still the next to be swaped\nand on NFU he won't be swaped\n");
  stop_for_ctrl_p();
  int i;
  for(i=0;i<30;i++)
    pages[5][10]='a';
  printf(1,"now page 10 in mem has the highest nfu value in the memory\n");
  printf(1,"now lets write to page 9 its on the file so we get page fault\n");
  pages[4][10]='a';
  printf(1,"now lets write to page 10\nhere on NFU we should not get page fault and on Fifo we should\n");
  pages[5][10]='a';
  //freePages(pageNum,pages);
  
}
void addremtest()
{
  char* b[20];
  char *pages[4];
  pages[0] = sbrk(PG_SIZE);
  pages[1] = sbrk(PG_SIZE);
  pages[2] = sbrk(PG_SIZE);
  pages[3] = sbrk(PG_SIZE);
  printf(1,"press ctrl p to check or enter to continue\n");
  read(1,b,1);
  free(pages[0]);
  free(pages[1]);
  free(pages[2]);
  free(pages[3]);
  printf(1,"press ctrl p to check or enter to continue\n");
  read(1,b,1);
}


void run_test1()
{
  printf(1,"fork test\n");
  forktest();
  printf(1,"end fork test\n");
  printf(1,"reading 1 character from each page\n");
  readtest();
  printf(1,"end reading test\n");
  printf(1,"adding pages and removing pages\n");
  addremtest();
  printf(1,"end adding and removing test\n");
  exit();
}

void run_test2()
{
 printf(1,"test2\n");
 nfu_vs_fifo_test();
}

int main(int argc, char **argv)
{
  //forktest();
  //multiplefork();
  //run_test2();
  readtest();
  // forktest();
 

  exit();
}
